#ifndef __BASE_OBJECT_HANDLER_HPP__
#define __BASE_OBJECT_HANDLER_HPP__

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <wx\wx.h>
#include <wx\propgrid\propgrid.h>

#include <SFML/System/Vector2.hpp>

#include "BaseXMLObject.hpp"

namespace smeg {
    namespace core {
        class PlaceableObject;
    }
}

namespace tinyxml2 {
    class XMLElement;
}

class SmegEditorCanvas;

////////////////////////////////////////////////////////////
/// Handler of an object in the scene
////////////////////////////////////////////////////////////
class BaseObjectHandler : public BaseXMLObject
{
public:
    ////////////////////////////////////////////////////////////
    /// Default Constructor
    ///
    ////////////////////////////////////////////////////////////
                            BaseObjectHandler();
    ////////////////////////////////////////////////////////////
    /// Copy Constructor
    ///
    /// \param _Copy :      Handler to copy from
    ///
    ////////////////////////////////////////////////////////////
                            BaseObjectHandler( const BaseObjectHandler& _Copy );
    ////////////////////////////////////////////////////////////
    /// Destructor
    ///
    ////////////////////////////////////////////////////////////
    virtual                 ~BaseObjectHandler() {}
    
    ////////////////////////////////////////////////////////////
    /// Does an update of things that doesn't usually happen
    ///
    ////////////////////////////////////////////////////////////
    virtual void            Update() {}
    
    ////////////////////////////////////////////////////////////
    /// Does an render of things that doesn't usually happen
    ///
    ////////////////////////////////////////////////////////////
    virtual void            Render() {}

    ////////////////////////////////////////////////////////////
    /// Init the handler from properties
    /// BaseObjectHandler::InitFromGrid need to be called AFTER the specialized class
    ///
    /// \param _pPropertyGrid :      Grid where infos are stored
    ///
    /// \return Whether the init was successful or not
    ///
    ////////////////////////////////////////////////////////////
    virtual bool            InitFromGrid( wxPropertyGrid* _pPropertyGrid );
    
    ////////////////////////////////////////////////////////////
    /// Init the handler from an XMLElement
    /// BaseObjectHandler::InitFromXML need to be called AFTER the specialized class
    ///
    /// \param _pElement :           XML Element with info
    /// \param _ProjectPath :        Path to the project
    ///
    /// \return Whether the init was successful or not
    ///
    ////////////////////////////////////////////////////////////
    virtual bool            InitFromXML( tinyxml2::XMLElement* _pElement, const wxString& _ProjectPath );
    
    ////////////////////////////////////////////////////////////
    /// Init the handler from properties
    /// BaseObjectHandler::Init need to be called AFTER the specialized class
    ///
    /// \param _pCanvas :            Canvas where the editor is drawn
    /// \param _pPropertyGrid :      Grid where infos are stored
    /// \param _Position :           Position of the handler
    /// \param _iIconId :            Icon id corresponding to the handler
    ///
    /// \return Whether the init was successful or not
    ///
    ////////////////////////////////////////////////////////////
    bool                    Init( SmegEditorCanvas* _pCanvas, wxPropertyGrid* _pPropertyGrid, const sf::Vector2f& _Position, int _iIconId = -1 );
    
    ////////////////////////////////////////////////////////////
    /// Init the handler from an XMLElement
    /// BaseObjectHandler::Init need to be called AFTER the specialized class
    ///
    /// \param _pCanvas :            Canvas where the editor is drawn
    /// \param _pElement :           XML Element with info
    /// \param _ProjectPath :        Path to the project
    /// \param _iIconId :            Icon id corresponding to the handler
    ///
    /// \return Whether the init was successful or not
    ///
    ////////////////////////////////////////////////////////////
    bool                    Init( SmegEditorCanvas* _pCanvas, tinyxml2::XMLElement* _pElement, const wxString& _ProjectPath, int _iIconId = -1 );
    
    ////////////////////////////////////////////////////////////
    /// Add the created object to the scene
    ///
    ////////////////////////////////////////////////////////////
    virtual void            AddObjectToScene() = 0;
    
    ////////////////////////////////////////////////////////////
    /// Remove the created object from the scene
    ///
    /// \param _bDeleteObject : Delete or not the object as well as removing it from the scene
    ///
    ////////////////////////////////////////////////////////////
    virtual void            RemoveObjectFromScene( bool _bDeleteObject = true ) = 0;
    
    ////////////////////////////////////////////////////////////
    /// Return the value of a property
    ///
    /// \param _PropertyName :      Name of the property
    ///
    /// \return The value as a string
    ///
    ////////////////////////////////////////////////////////////
    virtual wxString        GetValueAsString( const wxString& _PropertyName ) const;
    
    ////////////////////////////////////////////////////////////
    /// Handle the change of a property and apply it to the object
    ///
    /// \param _pPropertyGrid :      The property grid
    /// \param _pChangedProperty :   Property that has been changed
    ///
    /// \return Whether the object has been changed or not
    ///
    ////////////////////////////////////////////////////////////
    virtual bool            OnPropertyChanged( wxPropertyGrid* _pPropertyGrid, wxPGProperty* _pChangedProperty );
    
    ////////////////////////////////////////////////////////////
    /// Set the icon id of the object handler
    ///
    /// \param _iIconId : the icon id of the object handler
    ///
    ////////////////////////////////////////////////////////////
    void                    SetIconId( int _iIconId );
    
    ////////////////////////////////////////////////////////////
    /// Get the icon id of the object handler
    ///
    /// \return the icon id of the object handler
    ///
    ////////////////////////////////////////////////////////////
    int                     GetIconId() const;
    
    ////////////////////////////////////////////////////////////
    /// Get the created object
    ///
    /// \return the handled object
    ///
    ////////////////////////////////////////////////////////////
    smeg::core::PlaceableObject*  GetObject() const;
    
    ////////////////////////////////////////////////////////////
    /// Get the canvas
    ///
    /// \return the canvas
    ///
    ////////////////////////////////////////////////////////////
    SmegEditorCanvas*       GetCanvas() const;

protected:
    int                     m_iIconId;

    SmegEditorCanvas*       m_pCanvas;
    smeg::core::PlaceableObject*  m_pObject;
    
    ////////////////////////////////////////////////////////////
    /// Create an XML string with the value of the object
    ///
    /// \param _ProjectPath :   Path to the project
    /// \param _Tab :           Tab string to have a beautiful XML
    ///
    /// \return the XML String
    ///
    ////////////////////////////////////////////////////////////
    virtual wxString        InnerXMLString( const wxString& _ProjectPath = wxEmptyString, const wxString& _Tab = wxT( "\t" ) ) const;
};
    
////////////////////////////////////////////////////////////
/// Set the icon id of the object handler
////////////////////////////////////////////////////////////
inline void BaseObjectHandler::SetIconId( int _iIconId ) {
    m_iIconId = _iIconId;
}
    
////////////////////////////////////////////////////////////
/// Get the icon id of the object handler
////////////////////////////////////////////////////////////
inline int BaseObjectHandler::GetIconId() const {
    return m_iIconId;
}

////////////////////////////////////////////////////////////
/// Get the created object
////////////////////////////////////////////////////////////
inline smeg::core::PlaceableObject* BaseObjectHandler::GetObject() const {
    return m_pObject;
}
    
////////////////////////////////////////////////////////////
/// Get the canvas
////////////////////////////////////////////////////////////
inline SmegEditorCanvas* BaseObjectHandler::GetCanvas() const {
    return m_pCanvas;
}

#endif // __BASE_OBJECT_HANDLER_HPP__